//---------------------------------------------------------------------------

#ifndef h_designcontrolH
#define h_designcontrolH
//---------------------------------------------------------------------------
class TMainForm;
class HStage;
class HStageIcon;
class h_xml::HXmlTree;
class HCmdNewJob;
class HCmdDeleteJob;
class HCmdAddLink;
class HCmdRemoveLink;
class HCmdMove;
class HCmdPaste;
class HCmdAddGroup;
class HCmdRemoveGroup;
class HCmdMoveGroup;
class HCmdLoadGroup;
class HCmdEditProperty;
class HCmdEditBatchProperty;

class HDesignControl : public TScrollingWinControl
{
public :

        typedef TScrollingWinControl inherited;
        friend TMainForm;
        friend HCmdNewJob;
        friend HCmdDeleteJob;
        friend HCmdAddLink;
        friend HCmdRemoveLink;
        friend HCmdMove;
        friend HCmdPaste;
        friend HCmdAddGroup;
        friend HCmdRemoveGroup;
        friend HCmdMoveGroup;
        friend HCmdLoadGroup;
        friend HCmdEditProperty;
        friend HCmdEditBatchProperty;
        __fastcall virtual HDesignControl(Classes::TComponent* AOwner);
        __fastcall virtual ~HDesignControl(void);
        bool __fastcall GroupExist(const UTF8String &Name);
        UTF8String __fastcall GetGotoThisGroup(void);
        void __fastcall SelectAll();
        void __fastcall SelectHome();
        void __fastcall SelectEnd();
        bool __fastcall CanEditProperty();
        void __fastcall DoEditProperty();
        bool __fastcall CanDelete();
        void __fastcall DoDelete();
        bool __fastcall CanPaste();
        void __fastcall DoCut();
        void __fastcall DoCopy();
        void __fastcall DoPaste();
        void __fastcall SaveToJobList(map<UTF8String, HJobListInfo> &JobMap);
        HStage * __fastcall FindControlByName(const UTF8String &Name);
        void __fastcall SetFocusedJob(const UTF8String &Name,
           bool ScrollToCenter = false);

private :

        static const int GridInterval = 8;
        TControlCanvas *Canvas;

        struct HLinkInfo
        {
           UTF8String Name;
           UTF8String StartControl;
           UTF8String EndControl;
           vector<TPoint> LinePoints;
        };

        typedef enum { daNone, daBox, daDrag, daLink, daMove } HDragAction;
        HDragAction DragAction;
        int DragX;
        int DragY;
        int DragDeltaX;
        int DragDeltaY;

        void __fastcall DrawDragTrack();
        void __fastcall CancelDragAction();
        void __fastcall EndDragAction();

        map<UTF8String, HStage*> ControlMap;
        map<UTF8String, HLinkInfo> LinkMap;
        set<UTF8String> SelectedGroup;

        void __fastcall WMGetDlgCode(TWMGetDlgCode &Message);
        void __fastcall WMSetCursor(TWMSetCursor &Message);
        void __fastcall WMPaint(TWMPaint &Message);
        void __fastcall WMLButtonDown(TWMLButtonDown &Message);
        void __fastcall WMLButtonUp(TWMLButtonUp &Message);
        void __fastcall WMMouseMove(TWMMouseMove &Message);
        void __fastcall WMLButtonDblClk(TWMLButtonDblClk &Message);
        void __fastcall WMRButtonDown(TWMRButtonDown &Message);
        void __fastcall FormKeyDown(TObject *Sender, WORD &Key,
          TShiftState Shift);
        void __fastcall FormKeyUp(TObject *Sender, WORD &Key,
          TShiftState Shift);

        TColor __fastcall CalcColor(TColor BaseColor, int Percent);
        void __fastcall DrawLink(const UTF8String &Name, bool First);
        void __fastcall GetLinkPoints(const UTF8String &Name,
           vector<TPoint> &Points, int &Type);
        void __fastcall DrawDragRect(const TRect &Rect);
        UTF8String __fastcall FindControlByPos(int x, int y);
        void __fastcall UnselectControl(void);
        void __fastcall UnselectControl(const UTF8String &Name);
        void __fastcall DrawDragLine(const TRect &Rect);
        void __fastcall RemoveControl(const UTF8String &Name);
        UTF8String __fastcall FindLinkByPos(int x, int y);
        void __fastcall RemoveLink(const UTF8String &Name);
        void __fastcall RemoveLink(const UTF8String &StartJob,
           const UTF8String &EndJob);
        UTF8String __fastcall NewControlName(const UTF8String &Prefix);
        void __fastcall SelectControl(const UTF8String &Name);
        void __fastcall CombineRect(const vector<TRect> &RectVec,
           TRect &Rect);
        bool __fastcall ControlExist(const UTF8String &Name);
        void __fastcall SelectGroup(const TRect &Rect);
        bool __fastcall CheckAddLink(const UTF8String &Name1,
           const UTF8String &Name2);
        void __fastcall AddLink(const UTF8String &Name1,
           const UTF8String &Name2);
        void __fastcall GetAdjacentSet(const UTF8String &StartControl,
           set<UTF8String> &Result);
        UTF8String __fastcall NewLinkName(void);
        bool __fastcall LinkExist(const UTF8String &Name);
        void __fastcall OnDeactivate(void);
        void __fastcall SaveLinkToXmlTree(const UTF8String &Name,
           HXmlTree *XmlTree);
        void __fastcall SaveJobToXmlTree(const UTF8String &Name,
           HXmlTree *XmlTree);
        void __fastcall SaveToXmlTree(HXmlTree *XmlTree);
        void __fastcall LoadJobFromXmlTree(HXmlTree *XmlTree, bool XmlPropertyFlag);
        void __fastcall LoadFromXmlTree(HXmlTree *XmlTree, bool XmlPropertyFlag);
        void __fastcall AddBoundsRect(vector<TRect> &RectVec,
           const set<UTF8String> &JobSet);
        void __fastcall AdjustLinkLabel(const UTF8String &Name);

        list<HStageIcon*> IconList;
        void __fastcall AddIcon(HStageIcon *Icon);
        void __fastcall RemoveIcon(HStageIcon *Icon);
        void __fastcall BringToFront(HStageIcon *Icon);
        int __fastcall GetZOrder(HStageIcon *Icon);
        void __fastcall RefreshCaption();

protected :

        void __fastcall WndProc(TMessage &Message);
        BEGIN_MESSAGE_MAP
           VCL_MESSAGE_HANDLER(WM_GETDLGCODE, TWMGetDlgCode, WMGetDlgCode);
           VCL_MESSAGE_HANDLER(WM_SETCURSOR, TWMSetCursor, WMSetCursor);
           VCL_MESSAGE_HANDLER(WM_PAINT, TWMPaint, WMPaint);
           VCL_MESSAGE_HANDLER(WM_LBUTTONDOWN, TWMLButtonDown, WMLButtonDown);
           VCL_MESSAGE_HANDLER(WM_LBUTTONUP, TWMLButtonUp, WMLButtonUp);
           VCL_MESSAGE_HANDLER(WM_MOUSEMOVE, TWMMouseMove, WMMouseMove);
           VCL_MESSAGE_HANDLER(WM_LBUTTONDBLCLK, TWMLButtonDblClk,
              WMLButtonDblClk);
           VCL_MESSAGE_HANDLER(WM_RBUTTONDOWN, TWMRButtonDown, WMRButtonDown);
        END_MESSAGE_MAP(TScrollingWinControl);
};

class HCommand
{
public :
   __fastcall HCommand()
   {}
   virtual void __fastcall DoExecute() = 0;
   virtual void __fastcall DoUnexecute() = 0;
   void __fastcall Reexecute()
   {
      RestorePageStat();
      Execute();
   }
   void __fastcall Execute()
   {
      SavePageStat();
      DoExecute();
   }
   void __fastcall Unexecute()
   {
      DoUnexecute();
   }
   UTF8String __fastcall GetCaption()
   {
      return FCaption;
   }
   virtual ~HCommand()
   {}
protected :
   void __fastcall SavePageStat();
   void __fastcall RestorePageStat();
   int FPageIndex;
   int FHScrollPos;
   int FVScrollPos;
   UTF8String FCaption;
};

class HCmdNewJob : public HCommand
{
public :
   __fastcall HCmdNewJob(int x, int y, UTF8String Type)
      : Fx(x), Fy(y), FType(Type)
   {}
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdNewJob()
   {}
private :
   int Fx;
   int Fy;
   UTF8String FType;
   UTF8String FName;
};

class HCmdDeleteJob : public HCommand
{
public :
   __fastcall HCmdDeleteJob(const set<UTF8String> &JobSet)
      : FJobSet(JobSet)
   {
      FXml = new HXmlTree;
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdDeleteJob()
   {
      delete FXml;
   }
private :
   set<UTF8String> FJobSet;
   HXmlTree *FXml;
};

class HCmdAddLink : public HCommand
{
public :
   __fastcall HCmdAddLink(const UTF8String &StartJob, const UTF8String &EndJob)
      : FStartJob(StartJob), FEndJob(EndJob)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdAddLink()
   {
   }
private :
   UTF8String FStartJob;
   UTF8String FEndJob;
};

class HCmdRemoveLink : public HCommand
{
public :
   __fastcall HCmdRemoveLink(const UTF8String &StartJob,
      const UTF8String &EndJob)
      : FStartJob(StartJob), FEndJob(EndJob)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdRemoveLink()
   {
   }
private :
   UTF8String FStartJob;
   UTF8String FEndJob;
};

class HCmdMove : public HCommand
{
public :
   __fastcall HCmdMove(const set<UTF8String> &JobSet,
      int DeltaX, int DeltaY)
      : FJobSet(JobSet), FDeltaX(DeltaX), FDeltaY(DeltaY)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdMove()
   {
   }
private :
   set<UTF8String> FJobSet;
   int FDeltaX;
   int FDeltaY;
};

class HCmdPaste : public HCommand
{
public :
   __fastcall HCmdPaste(HXmlTree *XmlTree, int Delta)
      : FXml(XmlTree), FDelta(Delta)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdPaste()
   {
      delete FXml;
   }
private :
   HXmlTree *FXml;
   int FDelta;
};

class HCmdAddGroup : public HCommand
{
public :
   __fastcall HCmdAddGroup()
      : FPageIndex(0)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdAddGroup()
   {
   }
private :
   int FPageIndex;
};

class HCmdRemoveGroup : public HCommand
{
public :
   __fastcall HCmdRemoveGroup(int PageIndex, HXmlTree *XmlTree)
      : FPageIndex(PageIndex), FXml(XmlTree)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdRemoveGroup()
   {
      delete FXml;
   }
private :
   int FPageIndex;
   HXmlTree *FXml;
   UTF8String FGroupName;
};

class HCmdMoveGroup : public HCommand
{
public :
   __fastcall HCmdMoveGroup(int IndexFrom, int IndexTo)
      : FIndexFrom(IndexFrom), FIndexTo(IndexTo)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdMoveGroup()
   {
   }
private :
   int FIndexFrom;
   int FIndexTo;
};

class HCmdLoadGroup : public HCommand
{
public :
   __fastcall HCmdLoadGroup(HXmlTree *XmlTree, bool XmlPropertyFlag)
      : FXml(XmlTree), FXmlPropertyFlag(XmlPropertyFlag)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdLoadGroup()
   {
      delete FXml;
   }
private :
   HXmlTree *FXml;
   bool FXmlPropertyFlag;
};

class HCmdEditProperty : public HCommand
{
public :
   __fastcall HCmdEditProperty(const UTF8String &OldName, HXmlTree *OldXml,
      const UTF8String &NewName, HXmlTree *NewXml)
      : FOldName(OldName), FOldXml(OldXml), FNewName(NewName), FNewXml(NewXml)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdEditProperty()
   {
      delete FOldXml;
      delete FNewXml;
   }
private :
   UTF8String FOldName;
   HXmlTree *FOldXml;
   UTF8String FNewName;
   HXmlTree *FNewXml;
};

class HCmdEditBatchProperty : public HCommand
{
public :
   __fastcall HCmdEditBatchProperty(const UTF8String &OldName, HXmlTree *OldXml,
      const UTF8String &NewName, HXmlTree *NewXml)
      : FOldName(OldName), FOldXml(OldXml), FNewName(NewName), FNewXml(NewXml)
   {
   }
   virtual void __fastcall DoExecute();
   virtual void __fastcall DoUnexecute();
   virtual ~HCmdEditBatchProperty()
   {
      delete FOldXml;
      delete FNewXml;
   }
private :
   UTF8String FOldName;
   HXmlTree *FOldXml;
   UTF8String FNewName;
   HXmlTree *FNewXml;
};

#endif
